/*
 * Copyright 2011 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.core.utils
{
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;

	public dynamic class WeakCache extends Proxy
	{

		private var _cache:Object;

		private var _names:Array;

		public function WeakCache()
		{
			_cache = {};
		}

		flash_proxy override function deleteProperty(name:*):Boolean
		{
			processCache();
			return _cache[name];
		}

		flash_proxy override function getProperty(name:*):*
		{
			processCache();
			var entry:Entry = _cache[name];
			return entry === null ? null : entry.value;
		}

		flash_proxy override function hasProperty(name:*):Boolean
		{
			processCache();
			return name in _cache;
		}

		flash_proxy override function nextName(index:int):String
		{
			return _names[index - 1];
		}

		flash_proxy override function nextNameIndex(index:int):int
		{
			if (index == 0)
			{
				_names = [];
				for (var name:String in _cache)
				{
					var entry:Entry = _cache[name];
					if (entry.value === null)
					{
						delete _cache[name];
					}
					else
					{
						_names.push(name);
					}
				}
			}

			if (index < _names.length)
			{
				return index + 1;
			}
			else
			{
				return 0;
			}
		}

		flash_proxy override function nextValue(index:int):*
		{
			var entry:Entry = _cache[_names[index - 1]];
			return entry !== null ? entry.value : null;
		}


		flash_proxy override function setProperty(name:*, value:*):void
		{
			if (value === null)
			{
				flash_proxy::deleteProperty(name);
				return;
			}

			processCache();
			_cache[name] = new Entry(value);
		}

		private function processCache():void
		{
			for (var key:String in _cache)
			{
				var entry:Entry = _cache[key];
				if (entry.value === null)
				{
					delete _cache[key];
				}
			}
		}
	}
}

import flash.utils.Dictionary;

class Entry
{

	private var _holder:Dictionary;

	public function Entry(value:*)
	{
		_holder = new Dictionary(true);
		_holder[value] = true;
	}

	public function get value():*
	{
		for (var value:* in _holder)
		{
			return value;
		}

		return null;
	}
}
